

import os
import sys
import time
import socket
import multiprocessing as mp

import rpyc
from rpyc.utils import server
from rpyc.utils.factory import DiscoveryError

import dexen
from dexen.system.common import service
from dexen.system.common.service import DexenAddr
from dexen.system.node.slave import service as slave_srvc
from dexen.system.node.master import service as master_srvc
from dexen.system.common.constants import NODES_ROOT_DIR, TEMP_ROOT_DIR
from dexen.system.common.excepts import DexenRegistryDiscoveryError,\
    DexenConnectionError

#===============================================================================
# Globals
#===============================================================================
masters = {}
slaves = {}
num_slave_slots = None # Number of slave slots
NUM_MASTER_SLOTS = 1 # Number of master slots
is_local = None
is_quiet = None
node_name = None
start_time = None
reg_addr = None

#===============================================================================
# Service
#===============================================================================
class NodeService(dexen.Service):
        
    def create_master(self, master_name):
        print "%s is being created"%(master_name)
        proc = mp.Process(target=master_srvc.start, name=master_name, 
                          args=(master_name, node_name, reg_addr, is_local, 
                                is_quiet)) 
        masters[master_name] = proc
        proc.start()
        print "%s has started running with id:%s"%(master_name, proc.pid)
        time.sleep(0.1)
        
    def create_slave(self, slave_name):
        proc = mp.Process(target=slave_srvc.start, name=slave_name, 
                          args=(slave_name, node_name, reg_addr, is_local, 
                                is_quiet)) 
        slaves[slave_name] = proc
        proc.start()
        #time.sleep(0.1)
        conn = reg_addr.get_conn()
        for _ in xrange(10):
            slave_addr = conn.root.get_slave_addr(slave_name)
            slave_addr = rpyc.classic.obtain(slave_addr)
            if slave_addr: break
            time.sleep(0.5)
        print "%s has started."%(slave_name,)
        
    def is_alive(self):
        pass
    
    def n_slave_slots(self):
        return num_slave_slots
    
    def n_master_slots(self):
        return NUM_MASTER_SLOTS
    
    def test(self):
        pass

def _create_nodes_dir():
    if not os.path.exists(TEMP_ROOT_DIR):
        os.mkdir(TEMP_ROOT_DIR)        
    if not os.path.exists(NODES_ROOT_DIR):
        os.mkdir(NODES_ROOT_DIR)

def start(reg_host, _num_slave_slots, _is_quiet):
    global start_time, node_name, reg_addr, num_slave_slots, is_local, is_quiet
    num_slave_slots = _num_slave_slots
    is_local = service.is_local(reg_host)
    is_quiet = _is_quiet
    my_ip = service.get_my_ip(is_local)
    print "Dexen node is trying to connect to the server [%s]."%(reg_host,)
    print "Please wait..."
    reg_addr = service.get_reg_addr(reg_host)
    reg_conn = reg_addr.get_conn()
    _create_nodes_dir()    
    _logger = service.get_rpyc_logger("NODE", is_quiet=is_quiet)        
    
    svr = server.ThreadedServer(NodeService, 
                                protocol_config=service.default_config,
                                auto_register=False,
                                logger=_logger)
    my_addr = DexenAddr(my_ip, svr.port)
    start_time = time.time()
    node_name = reg_conn.root.register_node(start_time, my_addr)
    print "Dexen node has connected to the server [%s]."%(reg_host,)
    print "Dexen node is starting %s slaves."%(num_slave_slots,)    
    svr.start()
    
    
#===============================================================================
# Main
#===============================================================================
def main():
    pass


if __name__ == "__main__":
    main()
    
"""
    if is_local:
        ip = service.get_my_ip(is_local)
        port = service.REGISTRY_PORT
    else:
        try:
            host_list = rpyc.discover(reg_name, reg_ip)
            (ip, port) = host_list[0]
        except DiscoveryError:
            try:
                print "I am in first discovery error"
                (ip, port) = rpyc.discover(reg_name)[0]
            except DiscoveryError:
                print "I am in second discovery error"
                ip = reg_ip
                port = service.REGISTRY_PORT
        except socket.error:
            print "I am in socket.error"
            ip = reg_ip
            port = service.REGISTRY_PORT
"""